package org.example.lethear.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.lethear.dto.common.PageResult;
import org.example.lethear.dto.report.ReportCreateRequest;
import org.example.lethear.dto.report.ReportDTO;
import org.example.lethear.dto.report.ReportHandleRequest;
import org.example.lethear.entity.*;
import org.example.lethear.exception.BusinessException;
import org.example.lethear.exception.ForbiddenException;
import org.example.lethear.exception.ResourceNotFoundException;
import org.example.lethear.repository.*;
import org.example.lethear.utils.SecurityUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 举报管理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ReportService {
    
    private final ReportRepository reportRepository;
    private final UserRepository userRepository;
    private final PostRepository postRepository;
    private final CommentRepository commentRepository;
    private final WhisperRepository whisperRepository;
    private final ObjectMapper objectMapper;
    
    /**
     * 创建举报
     */
    @Transactional
    public ReportDTO createReport(ReportCreateRequest request) {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            throw new BusinessException("用户未登录");
        }
        
        // 检查是否已经举报过
        boolean alreadyReported = reportRepository.existsByReporterIdAndTargetTypeAndTargetId(
                currentUserId, request.getTargetType(), request.getTargetId());
        if (alreadyReported) {
            throw new BusinessException("您已经举报过此内容");
        }
        
        // 验证目标是否存在
        validateTargetExists(request.getTargetType(), request.getTargetId());
        
        // 检查是否是举报自己的内容
        if (isReportingOwnContent(currentUserId, request.getTargetType(), request.getTargetId())) {
            throw new BusinessException("不能举报自己的内容");
        }
        
        // 创建举报记录
        Report report = new Report();
        report.setReporterId(currentUserId);
        report.setTargetType(request.getTargetType());
        report.setTargetId(request.getTargetId());
        report.setReasonType(request.getReasonType());
        report.setReasonDetail(request.getReasonDetail());
        
        // 处理证据URLs
        if (request.getEvidenceUrls() != null && !request.getEvidenceUrls().isEmpty()) {
            try {
                report.setEvidenceUrls(objectMapper.writeValueAsString(request.getEvidenceUrls()));
            } catch (JsonProcessingException e) {
                log.warn("Failed to serialize evidence URLs: {}", e.getMessage());
            }
        }
        
        report.setStatus(Report.STATUS_PENDING);
        
        report = reportRepository.save(report);
        
        log.info("举报创建成功: userId={}, targetType={}, targetId={}, reportId={}", 
                currentUserId, request.getTargetType(), request.getTargetId(), report.getId());
        
        return convertToDTO(report);
    }
    
    /**
     * 处理举报（管理员功能）
     */
    @Transactional
    public ReportDTO handleReport(Long reportId, ReportHandleRequest request) {
        if (!SecurityUtils.isAdmin()) {
            throw new ForbiddenException("需要管理员权限");
        }
        
        Long currentUserId = SecurityUtils.getCurrentUserId();
        
        Report report = reportRepository.findById(reportId)
                .orElseThrow(() -> new ResourceNotFoundException("举报记录不存在"));
        
        if (!report.isPending()) {
            throw new BusinessException("举报记录已被处理");
        }
        
        // 更新举报状态
        report.setStatus(request.getStatus());
        report.setHandlerId(currentUserId);
        report.setHandleTime(LocalDateTime.now());
        report.setHandleResult(request.getHandleResult());
        
        // 如果需要删除目标内容
        if (Boolean.TRUE.equals(request.getDeleteTargetContent()) && 
            request.getStatus() == Report.STATUS_CONTENT_DELETED) {
            deleteTargetContent(report.getTargetType(), report.getTargetId());
        }
        
        report = reportRepository.save(report);
        
        log.info("举报处理完成: reportId={}, status={}, handlerId={}", 
                reportId, request.getStatus(), currentUserId);
        
        return convertToDTO(report);
    }
    
    /**
     * 获取举报列表（管理员功能）
     */
    public PageResult<ReportDTO> getReports(Integer status, Integer targetType, Integer reasonType,
                                           int page, int size) {
        if (!SecurityUtils.isAdmin()) {
            throw new ForbiddenException("需要管理员权限");
        }
        
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());
        Page<Report> reportPage;
        
        if (status != null && targetType != null) {
            reportPage = reportRepository.findByStatusAndTargetType(status, targetType, pageable);
        } else if (status != null && reasonType != null) {
            reportPage = reportRepository.findByStatusAndReasonType(status, reasonType, pageable);
        } else if (status != null) {
            reportPage = reportRepository.findByStatus(status, pageable);
        } else if (targetType != null) {
            reportPage = reportRepository.findByTargetType(targetType, pageable);
        } else if (reasonType != null) {
            reportPage = reportRepository.findByReasonType(reasonType, pageable);
        } else {
            reportPage = reportRepository.findAll(pageable);
        }
        
        List<ReportDTO> reportDTOs = reportPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return PageResult.of(reportDTOs, reportPage.getTotalElements(), page, size);
    }
    
    /**
     * 获取待处理举报列表
     */
    public PageResult<ReportDTO> getPendingReports(int page, int size) {
        if (!SecurityUtils.isAdmin()) {
            throw new ForbiddenException("需要管理员权限");
        }
        
        Pageable pageable = PageRequest.of(page - 1, size);
        Page<Report> reportPage = reportRepository.findPendingReports(pageable);
        
        List<ReportDTO> reportDTOs = reportPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return PageResult.of(reportDTOs, reportPage.getTotalElements(), page, size);
    }
    
    /**
     * 获取用户的举报记录
     */
    public PageResult<ReportDTO> getUserReports(int page, int size) {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            throw new BusinessException("用户未登录");
        }
        
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());
        Page<Report> reportPage = reportRepository.findByReporterId(currentUserId, pageable);
        
        List<ReportDTO> reportDTOs = reportPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return PageResult.of(reportDTOs, reportPage.getTotalElements(), page, size);
    }
    
    /**
     * 获取举报详情
     */
    public ReportDTO getReportById(Long reportId) {
        Report report = reportRepository.findById(reportId)
                .orElseThrow(() -> new ResourceNotFoundException("举报记录不存在"));
        
        // 检查权限：管理员或举报者本人可以查看
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (!SecurityUtils.isAdmin() && !report.getReporterId().equals(currentUserId)) {
            throw new ForbiddenException("无权限查看此举报记录");
        }
        
        return convertToDTO(report);
    }
    
    /**
     * 获取举报统计信息
     */
    public ReportStatsDTO getReportStats() {
        if (!SecurityUtils.isAdmin()) {
            throw new ForbiddenException("需要管理员权限");
        }
        
        long totalReports = reportRepository.count();
        long pendingReports = reportRepository.countPendingReports();
        long todayReports = reportRepository.countTodayReports(LocalDateTime.now().withHour(0).withMinute(0).withSecond(0));
        
        List<Object[]> reasonStats = reportRepository.countByReasonType();
        List<Object[]> targetStats = reportRepository.countByTargetType();
        List<Object[]> statusStats = reportRepository.countByStatus();
        
        return ReportStatsDTO.builder()
                .totalReports(totalReports)
                .pendingReports(pendingReports)
                .todayReports(todayReports)
                .reasonTypeStats(reasonStats)
                .targetTypeStats(targetStats)
                .statusStats(statusStats)
                .build();
    }
    
    /**
     * 验证目标是否存在
     */
    private void validateTargetExists(Integer targetType, Long targetId) {
        switch (targetType) {
            case Report.TARGET_TYPE_POST:
                if (!postRepository.existsById(targetId)) {
                    throw new ResourceNotFoundException("帖子不存在");
                }
                break;
            case Report.TARGET_TYPE_COMMENT:
                if (!commentRepository.existsById(targetId)) {
                    throw new ResourceNotFoundException("评论不存在");
                }
                break;
            case Report.TARGET_TYPE_USER:
                if (!userRepository.existsById(targetId)) {
                    throw new ResourceNotFoundException("用户不存在");
                }
                break;
            case Report.TARGET_TYPE_WHISPER:
                if (!whisperRepository.existsById(targetId)) {
                    throw new ResourceNotFoundException("悄悄话不存在");
                }
                break;
            default:
                throw new BusinessException("无效的目标类型");
        }
    }
    
    /**
     * 检查是否是举报自己的内容
     */
    private boolean isReportingOwnContent(Long reporterId, Integer targetType, Long targetId) {
        switch (targetType) {
            case Report.TARGET_TYPE_POST:
                return postRepository.findById(targetId)
                        .map(post -> post.getUserId().equals(reporterId))
                        .orElse(false);
            case Report.TARGET_TYPE_COMMENT:
                return commentRepository.findById(targetId)
                        .map(comment -> comment.getUserId().equals(reporterId))
                        .orElse(false);
            case Report.TARGET_TYPE_USER:
                return targetId.equals(reporterId);
            case Report.TARGET_TYPE_WHISPER:
                return whisperRepository.findById(targetId)
                        .map(whisper -> whisper.getSenderId() != null && whisper.getSenderId().equals(reporterId))
                        .orElse(false);
            default:
                return false;
        }
    }
    
    /**
     * 删除目标内容
     */
    private void deleteTargetContent(Integer targetType, Long targetId) {
        switch (targetType) {
            case Report.TARGET_TYPE_POST:
                postRepository.findById(targetId).ifPresent(post -> {
                    post.setStatus(0); // 软删除
                    postRepository.save(post);
                });
                break;
            case Report.TARGET_TYPE_COMMENT:
                commentRepository.findById(targetId).ifPresent(comment -> {
                    comment.setStatus(0); // 软删除
                    commentRepository.save(comment);
                });
                break;
            case Report.TARGET_TYPE_USER:
                userRepository.findById(targetId).ifPresent(user -> {
                    user.setStatus(0); // 禁用用户
                    userRepository.save(user);
                });
                break;
            case Report.TARGET_TYPE_WHISPER:
                whisperRepository.findById(targetId).ifPresent(whisper -> {
                    whisper.setStatus(0); // 软删除
                    whisperRepository.save(whisper);
                });
                break;
        }
    }
    
    /**
     * 转换为DTO
     */
    private ReportDTO convertToDTO(Report report) {
        ReportDTO.ReportDTOBuilder builder = ReportDTO.builder()
                .id(report.getId())
                .targetType(report.getTargetType())
                .targetTypeName(report.getTargetTypeName())
                .targetId(report.getTargetId())
                .reasonType(report.getReasonType())
                .reasonTypeName(report.getReasonTypeName())
                .reasonDetail(report.getReasonDetail())
                .status(report.getStatus())
                .statusName(report.getStatusName())
                .handleResult(report.getHandleResult())
                .createTime(report.getCreateTime())
                .handleTime(report.getHandleTime());
        
        // 解析证据URLs
        if (StringUtils.hasText(report.getEvidenceUrls())) {
            try {
                List<String> urls = objectMapper.readValue(report.getEvidenceUrls(), new TypeReference<List<String>>() {});
                builder.evidenceUrls(urls);
            } catch (JsonProcessingException e) {
                log.warn("Failed to parse evidence URLs: {}", e.getMessage());
                builder.evidenceUrls(new ArrayList<>());
            }
        } else {
            builder.evidenceUrls(new ArrayList<>());
        }
        
        // 举报者信息
        userRepository.findById(report.getReporterId()).ifPresent(user -> {
            ReportDTO.ReporterInfo reporterInfo = ReportDTO.ReporterInfo.builder()
                    .id(user.getId())
                    .username(user.getUsername())
                    .nickname(user.getProfile() != null ? user.getProfile().getNickname() : null)
                    .avatar(user.getAvatar())
                    .build();
            builder.reporter(reporterInfo);
        });
        
        // 处理者信息
        if (report.getHandlerId() != null) {
            userRepository.findById(report.getHandlerId()).ifPresent(user -> {
                ReportDTO.HandlerInfo handlerInfo = ReportDTO.HandlerInfo.builder()
                        .id(user.getId())
                        .username(user.getUsername())
                        .nickname(user.getProfile() != null ? user.getProfile().getNickname() : null)
                        .build();
                builder.handler(handlerInfo);
            });
        }
        
        // 目标内容信息
        ReportDTO.TargetContent targetContent = getTargetContent(report.getTargetType(), report.getTargetId());
        builder.targetContent(targetContent);
        
        return builder.build();
    }
    
    /**
     * 获取目标内容信息
     */
    private ReportDTO.TargetContent getTargetContent(Integer targetType, Long targetId) {
        switch (targetType) {
            case Report.TARGET_TYPE_POST:
                return postRepository.findById(targetId)
                        .map(post -> ReportDTO.TargetContent.builder()
                                .id(post.getId())
                                .title(post.getTitle())
                                .content(post.getContent().length() > 100 ? 
                                        post.getContent().substring(0, 100) + "..." : post.getContent())
                                .authorName(getUsernameById(post.getUserId()))
                                .createTime(post.getCreateTime())
                                .exists(post.getStatus() != 0)
                                .build())
                        .orElse(ReportDTO.TargetContent.builder()
                                .id(targetId)
                                .title("已删除的帖子")
                                .exists(false)
                                .build());
                                
            case Report.TARGET_TYPE_COMMENT:
                return commentRepository.findById(targetId)
                        .map(comment -> ReportDTO.TargetContent.builder()
                                .id(comment.getId())
                                .title("评论")
                                .content(comment.getContent().length() > 100 ? 
                                        comment.getContent().substring(0, 100) + "..." : comment.getContent())
                                .authorName(getUsernameById(comment.getUserId()))
                                .createTime(comment.getCreateTime())
                                .exists(comment.getStatus() != 0)
                                .build())
                        .orElse(ReportDTO.TargetContent.builder()
                                .id(targetId)
                                .title("已删除的评论")
                                .exists(false)
                                .build());
                                
            case Report.TARGET_TYPE_USER:
                return userRepository.findById(targetId)
                        .map(user -> ReportDTO.TargetContent.builder()
                                .id(user.getId())
                                .title("用户: " + user.getUsername())
                                .content(user.getProfile() != null ? user.getProfile().getBio() : "")
                                .authorName(user.getUsername())
                                .createTime(user.getCreateTime())
                                .exists(user.getStatus() != 0)
                                .build())
                        .orElse(ReportDTO.TargetContent.builder()
                                .id(targetId)
                                .title("不存在的用户")
                                .exists(false)
                                .build());
                                
            case Report.TARGET_TYPE_WHISPER:
                return whisperRepository.findById(targetId)
                        .map(whisper -> ReportDTO.TargetContent.builder()
                                .id(whisper.getId())
                                .title("悄悄话")
                                .content(whisper.getContent().length() > 100 ? 
                                        whisper.getContent().substring(0, 100) + "..." : whisper.getContent())
                                .authorName(whisper.getSenderNickname())
                                .createTime(whisper.getCreateTime())
                                .exists(whisper.getStatus() != 0)
                                .build())
                        .orElse(ReportDTO.TargetContent.builder()
                                .id(targetId)
                                .title("已删除的悄悄话")
                                .exists(false)
                                .build());
                                
            default:
                return ReportDTO.TargetContent.builder()
                        .id(targetId)
                        .title("未知内容")
                        .exists(false)
                        .build();
        }
    }
    
    /**
     * 根据用户ID获取用户名
     */
    private String getUsernameById(Long userId) {
        return userRepository.findById(userId)
                .map(User::getUsername)
                .orElse("未知用户");
    }
    
    /**
     * 举报统计DTO
     */
    @lombok.Data
    @lombok.Builder
    @lombok.NoArgsConstructor
    @lombok.AllArgsConstructor
    public static class ReportStatsDTO {
        private Long totalReports;
        private Long pendingReports;
        private Long todayReports;
        private List<Object[]> reasonTypeStats;
        private List<Object[]> targetTypeStats;
        private List<Object[]> statusStats;
    }
} 